<template>
    <div class="shell">
        <div class="top">
            <span class="tit">智能家居控制面板</span>
            <div>
                <span class="s-tit" v-if="people" style="color: rgb(93, 225, 93);font-weight: bold;">[当前有人]</span>
                <span class="s-tit" v-else style="color: rgb(154, 149, 149);font-weight: bold;">[当前无人]</span>
                <span class="s-tit" v-if="day" style="color: rgb(233, 242, 233);font-weight: bold;"> [白天]</span>
                <span class="s-tit" v-else style="color: rgb(154, 149, 149);font-weight: bold;"> [黑夜]</span>
            </div>
        </div>
        <div class="bottom">
            <canvas ref="can" :width="width" :height="height"></canvas>
        </div>
        <div class="l-t" style="text-align: left;width: 90%;font-size: 20px;font-weight: bold;margin: 5px 0px;">
            <span>控制按钮：</span>
            <div class="bswitch">
                <div>
                    <span>总开关：</span>
                    <el-switch
                        size="large"
                        v-model="all"
                        style="--el-switch-on-color: #92E3F5; --el-switch-off-color: #283258"
                        @click="postInfo('all')"
                    />
                </div>
                <div>
                    <span>智能模式：</span>
                    <el-switch
                        size="large"
                        v-model="mode"
                        style="--el-switch-on-color: #92E3F5; --el-switch-off-color: #283258"
                        @click="postInfo('mode')"
                    />
                </div>
            </div>
        </div>
        <div class="bnts">
            
            <div class="tbnt" :class="{'tbnt-no': !door}">
                <img v-if="door" src="@/assets/door-on.svg" alt="">
                <img v-else src="@/assets/door-off.svg" alt="">
                <span class="name">房间门</span>
                <div class="operate">
                    <span>{{door?'on':'off'}}</span>
                    <el-switch
                        v-model="door"
                        :disabled="!all"
                        style="--el-switch-on-color: #92E3F5; --el-switch-off-color: #283258"
                        @click="postInfo('door')"
                    />
                </div>
            </div>
            <div class="tbnt" :class="{'tbnt-no': !window}">
                <img v-if="window" src="@/assets/window-on.svg" alt="">
                <img v-else src="@/assets/window-off.svg" alt="">
                <span class="name">窗户</span>
                <div class="operate">
                    <span>{{window?'on':'off'}}</span>
                    <el-switch
                        v-model="window"
                        :disabled="!all"
                        style="--el-switch-on-color: #92E3F5; --el-switch-off-color: #283258"
                        @click="postInfo('windows')"
                    />
                </div>
            </div>
            <div class="tbnt" :class="{'tbnt-no': !fan}">
                <img v-if="fan" src="@/assets/fan-on.svg" alt="">
                <img v-else src="@/assets/fan-off.svg" alt="">
                <span class="name">风扇</span>
                <div class="operate">
                    <span>{{fan?'on':'off'}}</span>
                    <el-switch
                        v-model="fan"
                        :disabled="!all"
                        style="--el-switch-on-color: #92E3F5; --el-switch-off-color: #283258"
                        @click="postInfo('fan')"
                    />
                </div>
            </div>
            <div class="tbnt" :class="{'tbnt-no': !umbrella}">
                <img v-if="umbrella" src="@/assets/umbrella-on.svg" alt="">
                <img v-else src="@/assets/umbrella-off.svg" alt="">
                <span class="name">雨伞</span>
                <div class="operate">
                    <span>{{umbrella?'on':'off'}}</span>
                    <el-switch
                        v-model="umbrella"
                        :disabled="!all"
                        style="--el-switch-on-color: #92E3F5; --el-switch-off-color: #283258"
                        @click="postInfo('umbrella')"
                    />
                </div>
            </div>
        </div>
        <div class="lines">
            <div class="l-t" style="text-align: left;font-size: 20px;font-weight: bold;margin: 5px 0px;">环境数据：</div>
            <div class="line">
                <div class="label"><span>温度：{{ tempData.series[0].data[0] }}°C</span></div>
                <div class="chart" ref="temp">

                </div>
            </div>
            <div class="line">
                <div class="label"><span>湿度：{{ dampData.series[0].data[0] }}%RH</span></div>
                <div class="chart" ref="damp">

                </div>
            </div>
            <div class="line">
                <div class="label"><span>二氧化碳浓度：{{ co2Data.series[0].data[0] }}PPM</span></div>
                <div class="chart" ref="co2">

                </div>
            </div>
        </div>
    </div>
</template>

<script>
import * as echarts from 'echarts';
import * as mqtt from "mqtt/dist/mqtt"
export default {
    data(){
        return{
            door: false,
            window: false,
            fan: false,
            umbrella: false,
            people: false,
            all: false,
            day: true,
            mode: false,
            // 接收后端信息的主题
            topic: '/home/r/geek1',
            // 发送信息给后端的主题
            topic2: '/home/r/geek2',
            c: null,
            map: null,
            width: 220,
            height: 220,
            temp: 0,
            client: null,
            co2Data:{
                textStyle: {
                    color: "rgba(255,225,255,1)",
                },
                lineStyle: {
                    color: "rgb(74,208,238)",
                },
                xAxis:{
                    type: 'category',
                    data: ['1', '2', '3', '4', '5','6','7'],
                },
                yAxis:{
                    scale: true,
                    type: 'value'
                },
                series:[{
                    data: [],
                    type: 'line'
                }],
                grid: {
                    top: '10px',//生成的echarts图片和顶部的距离
                    bottom: '10px',//echarts图片和底部的距离
                    left: '1%',//echarts图片和左边的距离
                    right: '2%',//echarts图片和右边的间距,
                    containLabel: true//当containLabel:为ture时，以上设置生效
                },
            },
            dampData:{
                textStyle: {
                    color: "rgba(255,225,255,1)",
                },
                lineStyle: {
                    color: "rgb(74,208,238)",
                },
                xAxis:{
                    type: 'category',
                    data: ['1', '2', '3', '4', '5','6','7']
                },
                yAxis:{
                    scale: true,
                    minInterval: 1,
                    type: 'value'
                },
                series:[{
                    data: [],
                    type: 'line'
                }],
                grid: {
                    top: '10px',//生成的echarts图片和顶部的距离
                    bottom: '10px',//echarts图片和底部的距离
                    left: '1%',//echarts图片和左边的距离
                    right: '2%',//echarts图片和右边的间距,
                    containLabel: true//当containLabel:为ture时，以上设置生效
                },
            },
            tempData:{
                textStyle: {
                    color: "rgba(255,225,255,1)",
                },
                lineStyle: {
                    color: "rgb(74,208,238)",
                },
                xAxis:{
                    type: 'category',
                    data: ['1', '2', '3', '4', '5','6','7']
                },
                yAxis:{
                    scale: true,
                    type: 'value',
                    min: 0,
                    max: 50,
                },
                series:[{
                    data: [],
                    type: 'line'
                }],
                grid: {
                    top: '10px',//生成的echarts图片和顶部的距离
                    bottom: '10px',//echarts图片和底部的距离
                    left: '1%',//echarts图片和左边的距离
                    right: '2%',//echarts图片和右边的间距,
                    containLabel: true//当containLabel:为ture时，以上设置生效
                },
            },
        }
    },
    methods:{
        drawRing(cx, cy, outerRadius, innerRadius, color) {
            const ctx = this.c.getContext("2d");
            // 绘制外圆
            ctx.beginPath();
            ctx.arc(cx, cy, outerRadius, 0, Math.PI * 2, false);
            ctx.lineWidth = outerRadius - innerRadius;
            ctx.strokeStyle = color;
            ctx.stroke();
            // 可选：添加文本
            ctx.fillStyle = '#fff';
            ctx.font = 'bold 28px sans-serif';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(`${this.temp}°C`, cx, cy);
        },
        drawCir(cx, cy, outerRadius, innerRadius, color, percent) {
            const ctx = this.c.getContext("2d");
            // 绘制外圆
            ctx.beginPath();
            ctx.arc(cx, cy, outerRadius, Math.PI * 1.5, Math.PI * 1.5 * percent - Math.PI * 0.5, false);
            ctx.lineWidth = outerRadius - innerRadius;
            ctx.strokeStyle = color;
            ctx.lineCap = "round";
            ctx.lineJoin = "round";
            ctx.stroke();
        },
        // flag true顺时针
        test(flag,percent){
            var num = this.temp/100;
            this.temp = (percent * 100).toFixed(1);
            // 调整尺寸根据您的需求
            const cx = 110; // canvas的中心x坐标
            const cy = 110; // canvas的中心y坐标
            const outerRadius = 100; // 外圆的半径
            const innerRadius = 80; // 内圆的半径（圆环的宽度是outerRadius - innerRadius）
            const test = setInterval(()=>{
                this.map.clearRect(0, 0, this.width, this.height);
                if(flag){
                    if(num >= percent) clearInterval(test);
                    num += 1/350;
                }else{
                    if(num <= percent) clearInterval(test);
                    num -= 1/350;
                }
                this.drawRing(cx, cy, outerRadius, innerRadius, '#0F1D43');
                this.drawRing(cx, cy, 80, 50, '#2D3758');
                this.drawCir(cx, cy, 80, 54, '#48CAE7',num);
            },10)
        },
        initChart(tag) {
            if(tag == 1){
                this.chart = echarts.init(this.$refs.co2);
                const data = this.setMinMax(this.findMinMax(this.co2Data),this.co2Data)
                // 加载初始图表配置
                this.chart.setOption(data);
            }else if(tag == 2){
                this.chart2 = echarts.init(this.$refs.damp);
                const data = this.setMinMax(this.findMinMax(this.dampData),this.dampData)
                // 加载初始图表配置
                this.chart2.setOption(data);
            }else if(tag == 3){
                this.chart3 = echarts.init(this.$refs.temp);
                const data = this.setMinMax(this.findMinMax(this.tempData),this.tempData)
                // 加载初始图表配置
                this.chart3.setOption(data);
            }
        },
        // 更新图表数据的方法
        updateChartData() {
            this.chart.setOption(this.setMinMax(this.findMinMax(this.co2Data),this.co2Data));
            this.chart2.setOption(this.setMinMax(this.findMinMax(this.dampData),this.dampData));
            this.chart3.setOption(this.setMinMax(this.findMinMax(this.tempData),this.tempData));
        },
        findMinMax(data) {
            // 假设data是指向tempData对象的引用
            // 获取series数组中的第一组数据（如果有多组，你可能需要遍历它们）
            const seriesData = data.series[0].data;
            // 使用Math的min和max函数结合扩展运算符获取最小值和最大值
            const minValue = Math.min(...seriesData);
            const maxValue = Math.max(...seriesData);
            return { min: minValue, max: maxValue };
        },
        setMinMax(obj,tdata){
            const data = tdata;
            data.yAxis.max = obj.max+5;
            data.yAxis.min = obj.min-5;
            return data;
        },
        initMqtt() {
            // MQTT 服务器地址和端口、用户名、密码、客户端 ID
            const brokerUrl = `ws://192.168.1.101:8083/mqtt`;
            const username = 'admin';
            const password = '123456';
            const clientId = 'admin'+Math.floor(Math.random()*10000);
            // 连接 MQTT 服务器
            this.client = mqtt.connect(brokerUrl, {
                username: username,
                password: password,
                clientId: clientId
            });
            // 连接成功的回调函数
            this.client.on('connect', () => {
                console.log('成功接入MQTT服务器')
                this.status = "已连接"
                // 订阅主题
                this.client.subscribe(this.topic);
            });
            // 连接错误的回调函数
            this.client.on('error', (err) => {
                console.error('接入MQTT服务器失败', err);
                this.tip = "连接失败，请刷新重试并检查网络"
            });
            // 消息接收回调函数
            this.client.on('message', (topic, message) => {
                const info = message.toString();
                console.log(`主题：${this.topic}，接收信息:${info}`);
                if(this.checkJSON(info)) this.processInfo(info);
                else console.log("数据格式有误，非JSON！")
                // 在这里处理接收到的消息
            });
        },
        // 发送信息
        postInfo(str) {
            if(str == 'all'){
                if(this.all) this.client.publish(this.topic2, 'on');
                else this.client.publish(this.topic2, 'off');
                return ;
            }
            if(str == 'mode'){
                if(this.mode) this.client.publish(this.topic2, 'auto');
                else this.client.publish(this.topic2, 'hand');
                return ;
            }
            this.client.publish(this.topic2, 'hand');
            this.client.publish(this.topic2, str);
        },
        // 处理获取的数据
        async processInfo(info) { 
            const data = JSON.parse(info);
            // to do
            console.log(data);
            this.fan = !!data.fan;
            this.umbrella = !!data.umbrella;
            this.window = !!data.windows;
            this.door = !!data.door;
            this.people = !!data.hasPeople;
            this.all = !!data.state;
            this.day = !!data.color;
            this.mode = !!data.mode;
            var percent = data.temperature/100;
            if(this.temp!=data.temperature)
                if(percent > this.temp/100) this.test(true,percent);
                else this.test(false,percent);
            // 更新echart折线图数据
            this.dampData.series[0].data.push(data.humanity);
            if(this.dampData.series[0].data.length>7) this.dampData.series[0].data.shift(); 
            this.tempData.series[0].data.push(data.temperature);
            if(this.tempData.series[0].data.length>7) this.tempData.series[0].data.shift(); 
            this.co2Data.series[0].data.push(Math.floor(Math.random() * (571 - 570 + 1)) + 570);
            if(this.co2Data.series[0].data.length>7) this.co2Data.series[0].data.shift(); 
            // 更新折线图
            this.updateChartData();
        },
        // 检查数据格式是否是正确的JSON
        checkJSON(data) {
            try {
                JSON.parse(data);
                return true;
            } catch (error) {
                return false;
            }
        },
    },
    mounted(){
        this.c = this.$refs.can;
        // 获取设备屏幕像素大小
        const dpr = window.devicePixelRatio;
        const { width,height} = this.c;
        // 重新设置 canvas 自身宽高大小和 css 大小。放大 canvas；css 保持不变，因为我们需要那么多的点
        this.c.width = Math.round(width * dpr);
        this.c.height = Math.round(height * dpr);
        this.c.style.width = 200 + 'px';
        this.c.style.height = 200 + 'px';
        this.map = this.c.getContext("2d");
        // 直接用 scale 放大整个坐标系，相对来说就是放大了每个绘制操作
        this.map.scale(dpr, dpr);
        this.initMqtt();
        this.drawRing(110, 110, 100, 80, '#0F1D43');
        this.drawRing(110, 110, 80, 50, '#2D3758');
        this.drawCir(110, 110, 80, 54, '#2D3758',0);
        this.initChart(1);
        this.initChart(2);
        this.initChart(3);
        this.client.publish(this.topic2, 'off');
        console.log(window.innerWidth)
        // this.getDeviceLocation();
        // this.sent();
    }
}
</script>

<style lang="less" scoped>
*{
    margin: 0px;
    padding: 0px;
}
.pos{
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
.shell{
    .pos;
    overflow: hidden auto;
    background-color: #060F3A;
    width: 100%;
    min-height: 100vh;
    padding: 20px;
    box-sizing: border-box;
    margin: 0px;
    .top,.bottom.lines{
        .pos;
        margin-bottom: 16px;
    }
    .top{
        .tit{
            font-size: 20px;
        }
        .s-tit{
            margin-top: 6px;
            font-size: 14px;
            color: #7984A1;
        }
    }
    // 操作按钮
    .bnts{
        margin-top: 10px;
        width: 80vw;
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
        .tbnt{
            width: 36vw;
            height: 36vw;
            padding: 10px;
            box-sizing: border-box;
            background-color: #4AD0EE;
            transition: background-color 0.4s ease;
            border-radius: 14px;
            margin-bottom: 8px;
            display: flex;
            flex-direction: column;
            text-align: left;
            img{
                width: 30px;
                height: 30px;
                padding: 10px;
                background-color: #fff;
                border-radius: 40%;
            }
            .name{
                font-weight: bold;
                font-size: 18px;
                margin: 6px 0px;
            }
            .operate{
                display: flex;
                align-items: center;
                justify-content: space-between;
            }
        }
        // 关闭状态
        .tbnt-no{
            background-color: #101C45;
            transition: background-color 0.4s ease;
            img{
                background-color: #0C1734;
            }
        }
    }
    .lines{
        .line{
            .pos;
            align-items: left;
            .chart{
                .pos;
                width: 80vw;
                height: 160px;
                
            }
        }
    }
}
.bswitch{
    display: flex;
    align-items: center;
    justify-content: space-between;
}
/* PC端样式 */
@media only screen and (min-width: 769px) {
    .shell{
    .pos;
    overflow: hidden auto;
    background-color: #060F3A;
    width: 100vw;
    min-height: 100vh;
    padding: 20px 10vw;
    box-sizing: border-box;
    margin: auto;
    .top,.bottom.lines{
        .pos;
        margin-bottom: 16px;
    }
    .top{
        .tit{
            font-size: 20px;
        }
        .s-tit{
            margin-top: 6px;
            font-size: 14px;
            color: #7984A1;
        }
    }
    // 操作按钮
    .bnts{
        margin-top: 10px;
        width: 70vw;
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
        .tbnt{
            width: 15vw;
            height: 15vw;
            padding: 20px;
            box-sizing: border-box;
            background-color: #4AD0EE;
            transition: background-color 0.4s ease;
            border-radius: 14px;
            margin-bottom: 8px;
            display: flex;
            flex-direction: column;
            text-align: left;
            img{
                width: 30%;
                height: 30%;
                padding: 20px;
                background-color: #fff;
                border-radius: 40%;
            }
            .name{
                font-weight: bold;
                font-size: 28px;
                margin: 12px 0px 20px 0px;
            }
            .operate{
                font-size: 28px;
                display: flex;
                align-items: center;
                justify-content: space-between;
            }
        }
        // 关闭状态
        .tbnt-no{
            background-color: #101C45;
            transition: background-color 0.4s ease;
            img{
                background-color: #0C1734;
            }
        }
    }
    .lines{
        .line{
            .pos;
            align-items: left;
            margin-bottom: 20px;
            .chart{
                .pos;
                width: 72vw;
                height: 260px;
            }
        }
    }
}
.bswitch{
    justify-content: flex-start;
    & > div{
        margin-right: 10vw;
    }
}
}
</style>